﻿using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.Operation;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Orm;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using Kingdee.BOS.Web.Bill;
using Kingdee.BOS.WebApi.DataEntify;
using Kingdee.K3.Core.MFG.QM.ParamOption;
using Kingdee.K3.FIN.App.Core;
using RK.Tools;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
using System.Windows.Interop;

namespace RK.SerivesPlugin.ZhongRun
{
    [Description("ZhonRun:直接调拨单自动生成组织间调拨退回单_提交"), HotUpdate]
    public class AutoCreateBill : AbstractOperationServicePlugIn
    {
        public override void BeforeExecuteOperationTransaction(BeforeExecuteOperationTransaction e)
        {
            var obj = e.SelectedRows.Select(s => s.DataEntity).FirstOrDefault();
            string formId = this.BusinessInfo.GetForm().Id;
            //FFromOrg 要货事业部
            DynamicObject fromOrg = obj["FFromOrg"] as DynamicObject;
            int fromOrgId = fromOrg == null ? 0 : Convert.ToInt32(fromOrg["Id"]);
            string fromOrgName = fromOrg == null ? "" : fromOrg["name"].ToString();
            DynamicObject fromStock = obj["FFromStock"] as DynamicObject;
            int fromStockId = fromStock == null ? 0 : Convert.ToInt32(fromStock["Id"]);
            string fromStockName = fromStock == null ? "" : Convert.ToString(fromStock["Name"]);
            if (fromOrg != null)
            {
                if (fromStock == null)
                {
                    throw new Exception("填了要货事业部，必须填要货仓库！");
                }
                //调出库存组织
                DynamicObject outOrg = obj["StockOutOrgId"] as DynamicObject;
                int outOrgId = outOrg == null ? 0 : Convert.ToInt32(outOrg["Id"]);
                DynamicObjectCollection rows = obj["TransferDirectEntry"] as DynamicObjectCollection;
                List<Dictionary<DynamicObject, decimal>> dics = new List<Dictionary<DynamicObject, decimal>>();
                List<DynamicObject> newRows = new List<DynamicObject>();
                int i = 1;
                List<string> msgList = new List<string>();
                foreach (var row in rows)
                {
                    //物料编码
                    DynamicObject mat = row["MaterialId"] as DynamicObject;
                    string matNumber = mat == null ? "" : mat["number"].ToString();
                    //SrcStockId 调出仓库
                    DynamicObject srcStock = row["SrcStockId"] as DynamicObject;
                    int srcStockId = srcStock == null ? 0 : Convert.ToInt32(srcStock["Id"]);
                    //调出组织退时库存
                    string filterString = $"FMaterialId.fnumber='{matNumber}' and FStockOrgId={outOrgId} and FStockId={srcStockId}";
                    var curQty = Api.ExecuteBillQuery(this.Context, "STK_Inventory", "FBaseQty", filterString, "FBaseQty", 2000).Sum(s => Convert.ToDecimal(s.FirstOrDefault()));
                    //调拨数量（基本单位）
                    decimal baseQty = Convert.ToDecimal(row["BaseQty"]);
                    //要货数量
                    decimal fromQty = curQty - baseQty;
                    if (fromQty < 0)
                    {
                        fromQty = -fromQty;
                        filterString = $"FMaterialId.fnumber='{matNumber}' and FStockOrgId={fromOrgId} and FStockId={fromStockId}";
                        var fromOrgInvQty = Api.ExecuteBillQuery(this.Context, "STK_Inventory", "FBaseQty", filterString, "FBaseQty", 2000).Sum(s => Convert.ToDecimal(s.FirstOrDefault()));
                        if (fromOrgInvQty < fromQty)
                        {
                            string msg = $"要货事业部:{fromOrgName}第{i}行物料编码：{matNumber}需求量：{fromQty}，仓库：{fromStockName}的库存：{fromOrgInvQty}不足，不允许提交！";
                            msgList.Add(msg);
                        }
                        else
                        {
                            Dictionary<DynamicObject, decimal> keyValuePairs = new Dictionary<DynamicObject, decimal>();
                            keyValuePairs.Add(row, fromQty);
                            dics.Add(keyValuePairs);
                            newRows.Add(row);
                        }
                    }
                    i++;
                }
                if (msgList.Count > 0)
                {
                    foreach (var msg in msgList)
                    {
                        Base.AddOperationResult(this.OperationResult, false, msg, MessageType.FatalError, "要货事业部库存不足", 0);
                    }
                    e.Cancel = true;
                    return;
                }
                else if (dics.Count > 0)
                {
                    //下推调拨退货
                    List<string> list = new List<string>();
                    bool isOk = PushTranBill(newRows, outOrg, fromOrg, out list, dics, formId, this.OperationResult);
                    if (!isOk)
                    {
                        e.Cancel = true;
                        return;
                    }
                }

            }
            base.BeforeExecuteOperationTransaction(e);
        }

        private bool PushTranBill(List<DynamicObject> newRows, DynamicObject outOrg, DynamicObject fromOrg, out List<string> list, List<Dictionary<DynamicObject, decimal>> dics, string formId, IOperationResult operationResult)
        {
            FormMetadata meta = (FormMetadata)AppServiceContext.MetadataService.Load(this.Context, formId, true);
            OperateOption option = OperateOption.Create();
            list = new List<string>();
            List<DynamicObject> listObj = new List<DynamicObject>();
            foreach (var dic in dics)
            {
                var k = dic.Keys.FirstOrDefault();
                DynamicObject mat = k["MaterialId"] as DynamicObject;
                int matId = mat == null ? 0 : Convert.ToInt32(mat["Id"]);
                string matNumber = mat == null ? "" : mat["number"].ToString();
                var v = dic.Values.FirstOrDefault();
                DynamicObjectCollection seleList = GetSeleList(this.Context, outOrg, fromOrg, matNumber);
                if (seleList.Count > 0)
                {
                    foreach (var sel in seleList)
                    {
                        string eId = sel["FENTRYID"].ToString();
                        decimal qty = Convert.ToDecimal(sel["FBASEQTY"]);
                        var res = KingdeeTools.DzConvertService(this.Context, formId, formId, "FBillEntry", "", "", "", eId, "TransferDirect-TransferDirect");
                        decimal checkQty = 0;
                        if (qty < v)
                        {
                            checkQty = qty;
                        }
                        else
                        {
                            checkQty = v;
                        }
                        var tObj = AfterPush(res, checkQty);
                        listObj.AddRange(tObj);
                        v = v - qty;
                        if (v <= 0)
                        {
                            break;
                        }
                    }
                }
            }
            operationResult.MergeResult(AppServiceContext.SaveService.Save(this.Context, meta.BusinessInfo, listObj.ToArray(), option, ""));
            //IOperationResult operationResult = AppServiceContext.SaveService.Save(this.Context, meta.BusinessInfo, listObj.ToArray(), option, "");
            if (operationResult.IsSuccess)
            {
                var array = (from o in listObj
                             select o["Id"]).ToArray();
                operationResult.MergeResult(AppServiceContext.SubmitService.Submit(this.Context, meta.BusinessInfo, array, "Submit", null));
                if (operationResult.IsSuccess)
                {
                    operationResult.MergeResult(AppServiceContext.AuditService.Audit(this.Context, meta.BusinessInfo, array, OperateOption.Create()));
                    if (operationResult.IsSuccess)
                    {
                        var suObjs = operationResult.OperateResult;
                        var erRes = suObjs.GetFailResult();
                        var ereCount = erRes.Count();
                        if (ereCount > 0)
                        {
                            return false;
                        }
                        var sucRes = suObjs.GetSuccessResult();
                        var sucCount = sucRes.Count();
                        foreach (var sobj in suObjs)
                        {
                            var tbillno = sobj.Number;
                            var pkid = sobj.PKValue;
                        }
                    }
                }
            }
            return true;
        }

        private List<DynamicObject> AfterPush(ConvertOperationResult res, decimal checkQty)
        {
            if (!res.IsSuccess)
            {
                return null;
            }
            var array = res.TargetDataEntities.ToArray();
            List<DynamicObject> list = new List<DynamicObject>();
            foreach (var extData in array)
            {
                DynamicObject dataEntity = extData.DataEntity;
                DynamicObjectCollection rows = dataEntity["TransferDirectEntry"] as DynamicObjectCollection;
                foreach (var row in rows)
                {
                    row["Qty"] = checkQty;
                    row["BaseQty"] = checkQty;
                }
                //SetQtyFiels(dataEntity, checkQty, "Qty", "BaseQty");
                list.Add(dataEntity);
            }
            return list;
        }

        private void SetQtyFiels(DynamicObject dataEntity, decimal checkQty, string qty, string baseQty)
        {
            dataEntity[qty] = checkQty;
            dataEntity[baseQty] = checkQty;
        }

        private DynamicObjectCollection GetSeleList(Kingdee.BOS.Context ctx, DynamicObject outOrg, DynamicObject fromOrg, string matNumber)
        {
            int outOrgId = outOrg == null ? 1 : Convert.ToInt32(outOrg["Id"]);
            int fromOrgId = fromOrg == null ? 0 : Convert.ToInt32(fromOrg["Id"]);
            int matId = GetMatId(ctx, matNumber, fromOrgId);
            string sql = string.Format(@"/*dialect*/ 
            SELECT T0.FID, 
                   T1.FENTRYID, 
                   T1.FBASEQTY - T2.FBASEJOINQTY FBASEQTY
            FROM T_STK_STKTRANSFERIN T0
                 JOIN T_STK_STKTRANSFERINENTRY T1 ON T1.FID = T0.FID
                 JOIN T_STK_STKTRANSFERINENTRY_R T2 ON T2.FENTRYID = T1.FENTRYID
            WHERE T0.FSTOCKOUTORGID = {0}
                  AND T0.FSTOCKORGID = {1}
                  AND T0.FVESTONWAY = 'Dest'
                  AND T0.FDOCUMENTSTATUS = 'C'
                  AND T1.FMATERIALID = {2}
                  AND (T1.FBASEQTY - T2.FBASEJOINQTY) > 0 
            ORDER BY T0.FDATE ", outOrgId, fromOrgId, matId);
            DynamicObjectCollection doc = DBUtils.ExecuteDynamicObject(ctx, sql);
            return doc;
        }

        private int GetMatId(Context ctx, string matNumber, int fromOrgId)
        {
            string sql = string.Format(@"/*dialect*/ 
            SELECT FMATERIALID FROM T_BD_MATERIAL WHERE FNUMBER='{0}' AND FUSEORGID={1} ", matNumber, fromOrgId);
            DynamicObjectCollection doc = DBUtils.ExecuteDynamicObject(ctx, sql);
            if (doc.Count > 0)
            {
                return Convert.ToInt32(doc[0][0]);
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 加载所有列
        /// </summary>
        /// <param name="e"></param>
        public override void OnPreparePropertys(PreparePropertysEventArgs e)
        {
            base.OnPreparePropertys(e);
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(this.Context, this.BusinessInfo.GetForm().Id);
            var fieldKeyList = meta.BusinessInfo.GetBosFields().Select(x => x.Field.Key).ToList();
            for (int i = 0; i < fieldKeyList.Count; i++)
            {
                e.FieldKeys.Add(fieldKeyList[i]);
            }
        }
    }
}
